package com.rrd.dw.mr.gzip.bhzx;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer.Context;

import com.rrd.dw.utils.DateUtil;
import com.rrd.dw.utils.MD5Util;

/**
 * 处理当前已经结清的数据
 * 按每次还款记录计算,逾期用借款端的实际还款时间计算
 * @author liubaoxin
 *
 */
public class BHZXPayoffUtils3 {
	public static final String CRT_FLAG = "\001";
    public static final Pattern CRT_PATTERN = Pattern.compile(CRT_FLAG);
    private static NullWritable key_null = NullWritable.get();
	private static Text val_Text = new Text();
	private final static int K=0;
    
	public static void act_payoff(Context context,List<Map<String,String>> list_map) throws IOException, InterruptedException{
		double act_repay_amt=0;
		double arr[]=null;
		String target_repayment_date="";
		String target_repayment_date_k="";
		String payoff_date="";
		int term_no=0;
		double remaining_amount=0;
		double due_loan_amount=0;
		for(Map<String,String> map:list_map){ 
			payoff_date=time_to_date(map.get("payoff_time")); 
			target_repayment_date=time_to_date(map.get("target_repayment_date"));
			target_repayment_date_k=DateUtil.formateDateStr(DateUtil.addDay(DateUtil.formateToDate(target_repayment_date,"yyyy-MM-dd"), K+1),"yyyy-MM-dd");
			act_repay_amt=act_repay_amt+Double.parseDouble(map.get("planned_payment"));
			//提前结清正常还款的情况
			if(payoff_date.compareTo(target_repayment_date_k)<0){
				term_no=Integer.parseInt(map.get("term_no"));
				if(term_no==Integer.parseInt(map.get("last_period"))){
					map.put("loan_status", "3");
				}else {
					map.put("loan_status", "2");
				};
				map.put("target_repayment", String.valueOf(due_loan_amount));
				map.put("remaining_amount", String.valueOf(remaining_amount));
				map.put("term_status","normal");
				map.put("real_repayment_date",map.get("payoff_time")); //实际还款时间
				map.put("target_repayment",map.get("period_real_repayment"));
				map.put("real_repayment", map.get("period_real_repayment"));	
				map.put("overdue_status","");
				map.put("status_confirm_at",map.get("payoff_time"));
				map.put("act_repay_amt", String.valueOf(act_repay_amt));
				map.put("remaining_amount", String.valueOf(arr[1]));
				map.put("overdue_amount", String.valueOf(0)); //当 前 逾期总额
				map.put("repay_type", "");
				map.put("req_id", MD5Util.getMd5(map.get("repay_plan_key")+map.get("status_confirm_at")+map.get("term_status"))); 
				
				val_Text.set(processToString(map));
				context.write(key_null, val_Text);
				map.put("is_true", "true");//是否已经还了
				continue;
			}
			
			//逾期情况
			//如果连续多期实际还款时间相同，则属于一次还款(不包含部分提前还清),用本次还款最后一期作为上报期数
			if(payoff_date.equals(time_to_date(map.get("next_payoff_time"))) &&  payoff_date.compareTo(target_repayment_date_k)>=0){
				continue;
			}
			process_overdue(context,list_map,map.get("payoff_time"),term_no);
		}  
	}
	private static void process_overdue(Context context,List<Map<String,String>> list_maps,String act_payoff_time,int act_term_no) throws IOException, InterruptedException{
		double act_repay_amt=0;
		double arr[]=null;
		String target_repayment_date="";
		String next_target_repayment_date_k=null;
		int term_no=0;
		String act_payoff_date=time_to_date(act_payoff_time);
		for(Map<String,String> map :list_maps){
			target_repayment_date=time_to_date(map.get("target_repayment_date"));
			next_target_repayment_date_k=DateUtil.formateDateStr(DateUtil.addDay(DateUtil.formateToDate(map.get("next_due_date"),"yyyy-MM-dd"), K+1),"yyyy-MM-dd");
			
			//根据还款时间，判定本次还款进件所在期数
			if(act_payoff_date.compareTo(target_repayment_date)>=0 && act_payoff_date.compareTo(next_target_repayment_date_k)<0){
				term_no=Integer.parseInt(map.get("term_no"));
				arr = getLoan_due_amt(list_maps, term_no, act_term_no, act_payoff_date);
				
				map.put("real_repayment", String.valueOf(arr[2]));
				map.put("target_repayment", String.valueOf(arr[0]));
				map.put("remaining_amount", String.valueOf(arr[1]));
				map.put("term_status","normal");
				map.put("real_repayment_date",act_payoff_time); //实际还款时间
				map.put("overdue_status","");
				map.put("status_confirm_at",act_payoff_time);
				map.put("overdue_amount", String.valueOf(0)); //当 前 逾期总额
				map.put("repay_type", "");
				map.put("req_id", MD5Util.getMd5(map.get("repay_plan_key")+map.get("status_confirm_at")+map.get("term_status"))); 
				if(term_no==Integer.parseInt(map.get("last_period")) && act_payoff_date.equals(time_to_date(map.get("payoff_time")))){
					map.put("loan_status", "3");
				}else {
					map.put("loan_status", "2");
				};
				val_Text.set(processToString(map));
				context.write(key_null, val_Text);
			    break;	
			}
			
		}
	}
	 
	
	//计算当期剩余应还款金额、借款剩余余额、本次实际还款金额
		private static double[] getLoan_due_amt(List<Map<String,String>> list_maps,int term_no,int act_term_no,String act_payoff_date){
				double loan_due_amt=0;
				String payoff_date="";
				double remain_amt=0;
				double[] arr=new double[3];
				double act_amount=0;
				for(Map<String,String> m :list_maps){
					payoff_date=time_to_date(m.get("payoff_time"));
					if(Integer.parseInt(m.get("term_no"))<=term_no && !m.get("is_true").equals("true")){
						loan_due_amt=loan_due_amt+Double.parseDouble(m.get("period_real_repayment"));;
						
					}
					if(payoff_date.equals(act_payoff_date) && Integer.parseInt(m.get("term_no"))<=act_term_no){
						act_amount=act_amount+Double.parseDouble(m.get("period_real_repayment"));
						m.put("is_true", "true");
					}
					if(!m.get("is_true").equals("true")){
						remain_amt=remain_amt+Double.parseDouble(m.get("planned_payment"));
					}
	             }
				arr[0]=loan_due_amt;
				arr[1]=remain_amt;
				arr[2]=act_amount;
				return arr;
			}
		 
		private static String time_to_date(String datetime){
			 if(datetime.equals("")){
				 return "";
			 }else{
				 return datetime.substring(0, 10);
			 }
		 }
		/**
	 * map to string
	 * @param map
	 * @return
	 */
	public static String processToString(Map<String,String> map){
		map.put("op_code", "A"); 
		StringBuilder sb = new StringBuilder();
//		sb.append(MD5Util.getMd5(map.get("repay_plan_key")+map.get("status_confirm_at"))).append(CRT_FLAG);
		sb.append(map.get("loan_key")).append(CRT_FLAG);
		sb.append(map.get("repay_plan_key")).append(CRT_FLAG);
		sb.append(map.get("req_id")).append(CRT_FLAG);
		sb.append("A").append(CRT_FLAG); //op_code
		sb.append(map.get("uploadTs")).append(CRT_FLAG);
		sb.append(map.get("loan_id")).append(CRT_FLAG);
		sb.append(map.get("name")).append(CRT_FLAG);
		sb.append(map.get("pid")).append(CRT_FLAG);
		sb.append(map.get("mobile")).append(CRT_FLAG);
		sb.append(map.get("term_no")).append(CRT_FLAG);
		sb.append(map.get("term_status")).append(CRT_FLAG);
		sb.append(map.get("target_repayment_date")).append(CRT_FLAG);
		sb.append(map.get("real_repayment_date")).append(CRT_FLAG);
		sb.append(map.get("planned_payment")).append(CRT_FLAG);
		sb.append(map.get("target_repayment")).append(CRT_FLAG);
		sb.append(map.get("real_repayment")).append(CRT_FLAG);
		sb.append(map.get("overdue_status")).append(CRT_FLAG);
		sb.append(map.get("status_confirm_at")).append(CRT_FLAG);
		sb.append(map.get("overdue_amount")).append(CRT_FLAG);
		sb.append(map.get("remaining_amount")).append(CRT_FLAG);
		sb.append(map.get("loan_status")).append(CRT_FLAG);
		sb.append(map.get("act_repay_amt")).append(CRT_FLAG);
		sb.append(map.get("od_days")).append(CRT_FLAG);
		sb.append(map.get("payoff_time")).append(CRT_FLAG);
		sb.append(map.get("last_due_date")).append(CRT_FLAG);
		sb.append(map.get("loan_amt")).append(CRT_FLAG);
		sb.append(map.get("loan_payoff_time")).append(CRT_FLAG);
		sb.append(map.get("loan_platform")).append(CRT_FLAG);
		sb.append(map.get("loan_key")).append(CRT_FLAG);
		sb.append(map.get("repay_type"));
		return sb.toString();
		 
	}
}
